/*
 *  Gurr - A multiprotocol chat client for Android
 *  Copyright (C) 2011 Malte Aschermann, Wilfried Ramaker
 *  
 *  This file is part of Gurr.
 *  
 *  Gurr is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Lesser General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *  
 *  Gurr is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Lesser General Public License for more details.
 *  
 *  You should have received a copy of the GNU Lesser General Public License
 *  along with Gurr.  If not, see <http://www.gnu.org/licenses/>.
 */

package com.masc.gurr.model.xml;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;

import android.app.Activity;
import android.content.Context;
import android.os.Environment;

import com.masc.gurr.model.Account;
import com.masc.gurr.model.AccountMap;
import com.masc.gurr.model.Contact;
import com.masc.gurr.model.Group;
import com.masc.gurr.model.History;
import com.masc.gurr.model.Message;
import com.masc.gurr.model.ProtocolType;
import com.masc.gurr.model.Session;

public class Reader {
	
	public static final String FILE_HISTORY_PREFIX = "history_";
	public static final String FILE_CONTACTS_PREFIX = "contacts_";
	public static final String FILE_ACCOUNTS = "accounts.xml";

	public Group readContactList(Account pAccount, ProtocolType pProtocolType, Activity parent) {
		
		/** test for protocol type */
		if (pProtocolType.equals(ProtocolType.ICQ)) {
			return readContactListICQ(pAccount, parent);
		}
		
		return null;
	}
	
	private String getHistoryFName(String pStrUin) {
		return Reader.FILE_HISTORY_PREFIX + pStrUin + ".xml";
	}
	
	private String getContactsFName(String pStrUin) {
		return Reader.FILE_CONTACTS_PREFIX + pStrUin + ".xml";
	}
	
	
	public long getFreeSid(Activity parent, String pStrMyUin) {
		
		
		SAXBuilder builder = new SAXBuilder();

		try {
			FileInputStream in = parent.openFileInput(getHistoryFName(pStrMyUin));
			Document hdoc = builder.build(in);
			Element hroot = hdoc.getRootElement();

			long freeSid = Long.parseLong(hroot.getAttributeValue("freesid"));
			in.close();
			return freeSid;
			
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (JDOMException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (NumberFormatException e) {
			e.printStackTrace();
		}
		
		return -1;
	}
	
	public History readHistory(String pStrMyUin, Activity parent) {
		return readHistoryFile(pStrMyUin, parent);
	}
	
	private History readHistoryFile(String pStrMyUin, Activity parent) {
		
		/* make sure history exists */
		Writer writer = new Writer();
		writer.checkForHistory(pStrMyUin, parent);
		
		History history = new History(History.TYPE_PAST, pStrMyUin);
			
		/* read history.xml, get all references to session files and read them */
		
		SAXBuilder builder = new SAXBuilder();
		try {
			FileInputStream in = parent.openFileInput(getHistoryFName(pStrMyUin));
			Document hdoc = builder.build(in);
			Element hroot = hdoc.getRootElement();
			
			/* fail safe */
			if (! hroot.getAttributeValue("uin").equals(pStrMyUin))
				return history;
			
			history.setMyUin(pStrMyUin);
			
			/* parse elements of each buddy's sessions */
			List<Element> elHSessions = hroot.getChildren("sessions");
			for (Element elSessions : elHSessions) {
				
				/* read each session into history */
				List<Element> elS = elSessions.getChildren("session");
				for (Element el : elS) {
					readSession(
							history, 
							elSessions.getAttributeValue("buddy"), 
							el.getAttributeValue("file"),
							Long.parseLong(el.getAttributeValue("sid")),
							parent
							);
				}
				
			}
			in.close();
			
		} catch (JDOMException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (NumberFormatException e) {
			e.printStackTrace();
		}

		return history;
	}
	
	private void readSession(History pHistory, String pStrBuddyUin, String pFileSession, long pLSid, Activity parent) {
		
		SAXBuilder builder = new SAXBuilder();
		try {
			FileInputStream in = parent.openFileInput(pFileSession);
			Document sdoc = builder.build(in);
			Element sroot = sdoc.getRootElement();
			
			if (! (sroot.getAttributeValue("sid").equals(String.valueOf(pLSid)) 
					&& sroot.getAttributeValue("buddy").equals(pStrBuddyUin)) )
				return;
			
			Session s = pHistory.addSession(pStrBuddyUin, pHistory.getMyUin(), ProtocolType.ICQ);

			/* read messages */
			List<Element> elLstM = sroot.getChildren("message");
			long currMsgId=0;
			for (Element elM : elLstM) {
				
				s.addMessage(
						elM.getAttributeValue("sender"), 
						elM.getText(), 
						new Date(Long.parseLong(elM.getAttributeValue("date"))),
						currMsgId);
				currMsgId++;
				
			}
			s.setSetCurrMsgId(currMsgId);
			in.close();
		} catch (JDOMException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (NumberFormatException e) {
			e.printStackTrace();
		}
	}
	
	/** parse icq contact list and return as group/contact model */ 
	private Group readContactListICQ(Account pAccount, Activity parent) {
		
		Group groupRootElement = new Group("/");
		SAXBuilder builder = new SAXBuilder();
		try {
			FileInputStream in = parent.openFileInput(getContactsFName(pAccount.getUin()));
			Document doc = builder.build(in);
			Element root = doc.getRootElement();
			parseContactListICQ(root, groupRootElement);
			in.close();
		} catch (JDOMException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return groupRootElement;
	}

	private void parseContactListICQ(Element current, Group group) {
		List children = current.getChildren();
		Iterator iterator = children.iterator();
		if (current.getName().equals("group") ) {
			Group g = new Group(current.getAttributeValue("name"));
			group.addSubGroup(g);
			group = g;
		}
		else if (current.getName().equals("contact") ) {
			Contact c = new Contact(
					current.getAttributeValue("uin"),
					current.getAttributeValue("name"),
					ProtocolType.ICQ,
					current.getAttributeValue("statusmsg"));
			group.addContact(c);
		}
		
		while (iterator.hasNext()) {
			Element child = (Element) iterator.next();
			parseContactListICQ(child, group);	
		}
	}

	public AccountMap readAccounts(Activity parent) {
		return readAccountsFile(parent);
	}

	private AccountMap readAccountsFile(Activity parent) {
		AccountMap accountMap = new AccountMap();
		try {
			
			SAXBuilder builder = new SAXBuilder();
		
			/* test if accounts.xml already exists */
			boolean fileAccountsExist = false;
			String[] fileList = parent.fileList();
			System.out.println(fileList);
			for (String file : parent.fileList()) {
				if (file.equals(Reader.FILE_ACCOUNTS)) {
					fileAccountsExist = true;
					break;
				}
			}
			if (! fileAccountsExist)
				return accountMap;
			
			FileInputStream in = parent.openFileInput(Reader.FILE_ACCOUNTS);
			Document doc = builder.build(in);
			Element root = doc.getRootElement();
			
			List<Element> elAccounts = root.getChildren("account");
			for(Element e : elAccounts) {
				accountMap.addAccount(
						ProtocolType.values()[Integer.parseInt(e.getAttributeValue("type"))],
						e.getAttributeValue("uin"), 
						e.getAttributeValue("pass"), 
						e.getAttributeValue("alias")
						);
			}
			in.close();
			return accountMap;
		} catch (JDOMException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		return accountMap;
	}
}